package path;

import geom.Geom;
import geom.PolarVector;
import geom.Vector;
import geom.VectorSpace;

import java.util.ArrayList;
import java.util.Iterator;

import processing.core.PApplet;
import processing.core.PMatrix;
import processing.opengl.*;
import shapes.Vertex;

public class DrawPeakPath implements PathDrawer{
	ArrayList center;
	ArrayList left;
	ArrayList right;
	ArrayList intersections;
	float width;
	float height;
	
	public DrawPeakPath(float width, float height) {
		center = new ArrayList();
		left = new ArrayList();
		right = new ArrayList();
		this.width = width;
		this.height = height;
		intersections = new ArrayList();
	}

	public void keysAdded(Path p, int amount){
		if(p.getSize() <= 2) return;
		int backStep = 0;
		if(left.size() >= 2 && right.size() >= 2){
			left.remove(left.size()-1);
			right.remove(right.size()-1);
			center.remove(center.size()-1);
			backStep = 1;
		}
		for(int i = p.getSize() - amount - backStep; i < p.getSize(); i++){
			Vector[] outline = getOutline(p, i, width);
			Vector c = p.getKeyFrameByIndex(i).getPosition();
			left.add(outline[0]);
			center.add(outline[1]);
			right.add(outline[2]);
			//if(i > 0)
			//	intersectionTest(left.size()-1);
		}
	}
	
	public void intersectionTest(int k){
		int i = k-1;
		while(i > 0){
			float[] x = Geom.intersectLineAndPlane(
				getLeftVertex(k), getRightVertex(k), new Vertex(), 
				getLeftVertex(i), getRightVertex(i));
			if(x != null){
				if(x[0] >= 0 && x[0] <= 1 && x[1] >= 0 && x[1] <= 1){
					//System.out.println("intersect");
					if(x[0] > 0.5f){
						Vector avg = getRightVertex(k).getCenter(getRightVertex(i));
						getRightVertex(k).set(avg);
						getRightVertex(i).set(avg);
						intersections.add(avg);
					}
					else{
						Vector avg = getLeftVertex(k).getCenter(getLeftVertex(i));
						getLeftVertex(k).set(avg);
						getLeftVertex(i).set(avg);
						intersections.add(avg);
					}
				}
			}
			i--;
		}

	}

	public void keyRemoved(Path p, int i) {
		if(left.size() <= i) return;
		//System.out.println("remove: " + i + " size " + left.size());
		left.remove(i);
		right.remove(i);
		center.remove(i);
	}
	
	public void keyAdded(Path p) {
		keysAdded(p, 1);
	}
	
	public void drawPath(Path path, PApplet pa) {
		/*
		pa.stroke(10, 30, 120, 200);
		for(int i = 0; i < left.size(); i++){
			pa.beginShape(PApplet.LINE_STRIP);
			pa.strokeWeight(1);
			getLeftVertex(i).draw(pa);
			pa.strokeWeight(5);
			getCenterVertex(i).draw(pa);
			pa.strokeWeight(1);
			getRightVertex(i).draw(pa);
			pa.endShape();
		}
		*/
		
		pa.stroke(255);
		pa.noStroke();
		pa.fill(15, 20, 220, 150);
		
		//pa.noFill();
		for(int i = 1; i < left.size(); i++){
			if(path.getKeyFrameByIndex(i-1).getVisibility() > 0.01){
				pa.beginShape(PApplet.QUADS);
				getLeftVertex(i-1).draw(pa);
				getCenterVertex(i-1).draw(pa);
				//pa.fill(15, 20, 220, path.getKeyFrameByIndex(i).getVisibility() * 255f);
				getCenterVertex(i).draw(pa);
				getLeftVertex(i).draw(pa);
				pa.endShape();
				
				pa.beginShape(PApplet.QUADS);
				//pa.fill(15, 20, 220, path.getKeyFrameByIndex(i-1).getVisibility() * 255f);
				getCenterVertex(i-1).draw(pa);
				getRightVertex(i-1).draw(pa);
				//pa.fill(15, 20, 220, path.getKeyFrameByIndex(i).getVisibility() * 255f);
				getRightVertex(i).draw(pa);
				getCenterVertex(i).draw(pa);
				pa.endShape();
				/*
				pa.beginShape(PApplet.QUADS);
				getRightVertex(i-1).draw(pa);
				getRightVertex(i).draw(pa);
				getLeftVertex(i).draw(pa);
				getLeftVertex(i-1).draw(pa);
				pa.endShape();
				*/
			}
		}
		
	}

		
	private void scaleWidth(int i, float scale){
		Vector vLeft, vCenter, vRight;
		vLeft = (Vector)left.get(i);
		vCenter = (Vector)center.get(i);
		vRight = (Vector)right.get(i);
		vLeft = vLeft.sub(vCenter).mult(scale).add(vCenter);
		vRight = vRight.sub(vCenter).mult(scale).add(vCenter);
	}
	
	private Vertex[] getOutline(Path p, int i, float width){
		KeyFrame kf1 = null, kf2, kf3 = null;
		
		VectorSpace tnbSpace = null;
		
		kf2 = p.getKeyFrameByIndex(i);
		if(i > 0 && i < p.getSize() - 1){ 
			kf1 = p.getKeyFrameByIndex(i-1);
			kf3 = p.getKeyFrameByIndex(i+1);
			
		}
		
		else if(i == 0 && i < p.getSize() -1){
			kf1 = p.getKeyFrameByIndex(i);
			kf3 = p.getKeyFrameByIndex(i+1);
		}
		else if(i >= p.getSize() - 1 && i > 0){
			kf1 = p.getKeyFrameByIndex(i-1);
			kf3 = p.getKeyFrameByIndex(i);
		}
		
		else return new Vertex[]{
			new Vertex(new Vector(kf2.getPosition())),
			new Vertex(new Vector(kf2.getPosition())),
			new Vertex(new Vector(kf2.getPosition()))
		};
		
		tnbSpace = VectorSpace.newVectorSpaceFromCurveAndCenter(kf1.getPosition(), kf2.getPosition(), kf3.getPosition(), new Vector());
		
		Vertex left = new Vertex(
			tnbSpace.getOrthoCoord(new Vector(0, width, 0)),
			tnbSpace.getY(), kf1.getVisibility()
		);
		Vertex center = new Vertex(
			tnbSpace.getOrthoCoord(new Vector(0, 0, -height)), 
			tnbSpace.getZ().mult(-1f), kf2.getVisibility()
		);
		Vertex right = new Vertex(
			tnbSpace.getOrthoCoord(new Vector(0,-width, 0)), 
			tnbSpace.getY().mult(-1f), kf3.getVisibility()
		);
		
		return new Vertex[]{left, center, right};
	}

	public Vertex getLeftVertex(int i){
		return (Vertex)left.get(i);
	}
	
	public Vertex getRightVertex(int i){
		return (Vertex)right.get(i);
	}
	
	public Vertex getCenterVertex(int i){
		return (Vertex)center.get(i);
	}

}
